package com.bank.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.hutool.crypto.digest.MD5;

import com.bank.backend.mapper.DepositMapper;
import com.bank.backend.mapper.CardMapper;
import com.bank.backend.mapper.TradeMapper;
import com.bank.backend.model.entity.Deposit;
import com.bank.backend.model.entity.Card;
import com.bank.backend.model.entity.Trade;
import com.bank.backend.model.dto.DepositCreateDTO;
import com.bank.backend.model.dto.DepositQueryDTO;
import com.bank.backend.model.dto.DepositUpdateDTO;
import com.bank.backend.model.dto.WithdrawDTO;
import com.bank.backend.service.DepositService;
import com.bank.backend.exception.BusinessException;
import com.bank.backend.enums.ErrorCode;
import com.bank.backend.model.vo.DepositVO;
import com.bank.backend.result.PageResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDate;

/**
 * 存款类型业务实现类
 */
@Service
public class DepositServiceImpl extends ServiceImpl<DepositMapper, Deposit> implements DepositService {
    private static final Logger log = LoggerFactory.getLogger(DepositServiceImpl.class);

    @Autowired
    private CardMapper cardMapper;

    @Autowired
    private TradeMapper tradeMapper;

    @Override
    public void createDeposit(DepositCreateDTO dto) {
        // 唯一性校验：同名且未删除的存款类型不允许重复
        long count = this.count(new LambdaQueryWrapper<Deposit>()
                .eq(Deposit::getDepositName, dto.getDepositName())
                .eq(Deposit::getIsDeleted, false));
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "存款类型名称已存在");
        }
        Deposit deposit = new Deposit();
        BeanUtils.copyProperties(dto, deposit);
        deposit.setCreateTime(LocalDateTime.now());
        deposit.setUpdateTime(LocalDateTime.now());
        this.save(deposit);
    }

    @Override
    public void deleteDeposit(Integer depositId) {
        // 校验是否有关联银行卡
        Long cardCount = cardMapper.selectCount(new LambdaQueryWrapper<Card>()
                .eq(Card::getDepositId, depositId)
                .eq(Card::getIsDeleted, 0));
        if (cardCount != null && cardCount > 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "有银行卡正在使用该存款类型，无法删除");
        }
        this.removeById(depositId);
    }

    @Override
    public PageResult<DepositVO> pageDepositList(DepositQueryDTO queryDTO) {
        Page<Deposit> pageObj = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        LambdaQueryWrapper<Deposit> wrapper = new LambdaQueryWrapper<>();
        
        // 存款类型名称查询
        if (queryDTO.getDepositName() != null && !queryDTO.getDepositName().trim().isEmpty()) {
            wrapper.like(Deposit::getDepositName, queryDTO.getDepositName().trim());
        }
        
        // 时间范围查询
        if (queryDTO.getStartTime() != null && !queryDTO.getStartTime().trim().isEmpty()) {
            try {
                LocalDate startDate = LocalDate.parse(queryDTO.getStartTime().trim());
                LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
                wrapper.ge(Deposit::getCreateTime, startDateTime);
            } catch (Exception e) {
                log.warn("Invalid startTime format: {}", queryDTO.getStartTime());
            }
        }
        if (queryDTO.getEndTime() != null && !queryDTO.getEndTime().trim().isEmpty()) {
            try {
                LocalDate endDate = LocalDate.parse(queryDTO.getEndTime().trim());
                LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
                wrapper.le(Deposit::getCreateTime, endDateTime);
            } catch (Exception e) {
                log.warn("Invalid endTime format: {}", queryDTO.getEndTime());
            }
        }
        
        wrapper.eq(Deposit::getIsDeleted, 0);
        wrapper.orderByDesc(Deposit::getCreateTime);
        
        Page<Deposit> depositPage = this.page(pageObj, wrapper);
        ArrayList<DepositVO> voList = new ArrayList<>();
        for (Deposit deposit : depositPage.getRecords()) {
            DepositVO vo = new DepositVO();
            BeanUtils.copyProperties(deposit, vo);
            voList.add(vo);
        }
        PageResult<DepositVO> result = new PageResult<>();
        result.setTotal(depositPage.getTotal());
        result.setPage((int) depositPage.getCurrent());
        result.setSize((int) depositPage.getSize());
        result.setRecords(voList);
        return result;
    }
    @Override
    public void updateDeposit(DepositUpdateDTO dto) {
        // 先查询原有的存款类型信息
        Deposit existingDeposit = this.getById(dto.getDepositId());
        if (existingDeposit == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "存款类型不存在");
        }
        // 只更新非null的字段
        if (dto.getDepositName() != null) {
            existingDeposit.setDepositName(dto.getDepositName());
        }
        if (dto.getDescription() != null) {
            existingDeposit.setDescription(dto.getDescription());
        }
        if (dto.getTermYears() != null) {
            existingDeposit.setTermYears(dto.getTermYears());
        }
        existingDeposit.setUpdateTime(LocalDateTime.now());
        this.updateById(existingDeposit);
    }

    @Override
    public DepositVO getDepositById(Integer depositId) {
        // 查询存款类型信息
        Deposit deposit = this.getById(depositId);
        if (deposit == null || deposit.getIsDeleted() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "存款类型不存在");
        }
        // 转换为VO对象
        DepositVO vo = new DepositVO();
        BeanUtils.copyProperties(deposit, vo);
        return vo;
    }

    @Override
    @Transactional
    public void deposit(String cardId, Double amount, String remark) {
        if (amount == null || amount < 1) {
            throw new IllegalArgumentException("单笔存款不能小于1元");
        }
        // 1. 查询卡信息
        Card card = cardMapper.selectById(cardId);
        if (card == null || card.getIsDeleted() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "卡号不存在");
        }
        // 新增：挂失校验
        if (card.getIsReportLoss() != null && card.getIsReportLoss() == 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该银行卡已挂失，无法进行存款操作");
        }
        // 2. 更新余额
        card.setBalance(card.getBalance().add(BigDecimal.valueOf(amount)));
        card.setUpdateTime(LocalDateTime.now());
        cardMapper.updateById(card);
        // 3. 生成交易记录
        Trade trade = new Trade();
        trade.setCardId(cardId);
        trade.setTradeDate(LocalDateTime.now());
        trade.setTradeType("存入");
        trade.setTradeMoney(BigDecimal.valueOf(amount));
        trade.setRemark(remark);
        trade.setCreateTime(LocalDateTime.now());
        trade.setUpdateTime(LocalDateTime.now());
        tradeMapper.insert(trade);
    }

    @Override
    @Transactional
    public void withdraw(WithdrawDTO dto) {
        String cardId = dto.getCardId();
        Double amount = dto.getAmount();
        String password = dto.getPassword();
        String remark = dto.getRemark();
        if (amount == null || amount < 1) {
            throw new IllegalArgumentException("单笔取款不能小于1元");
        }
        // 1. 查询卡信息
        Card card = cardMapper.selectById(cardId);
        if (card == null || card.getIsDeleted() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "卡号不存在");
        }
        // 新增：挂失校验
        if (card.getIsReportLoss() != null && card.getIsReportLoss() == 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该银行卡已挂失，无法进行取款操作");
        }
        // 2. 校验密码
        password = MD5.create().digestHex(password);
        if (!password.equals(card.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
        }
        // 3. 校验余额
        if (card.getBalance().compareTo(BigDecimal.valueOf(amount)) < 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "余额不足");
        }
        // 4. 更新余额
        card.setBalance(card.getBalance().subtract(BigDecimal.valueOf(amount)));
        card.setUpdateTime(LocalDateTime.now());
        cardMapper.updateById(card);
        // 5. 生成交易记录
        Trade trade = new Trade();
        trade.setCardId(cardId);
        trade.setTradeDate(LocalDateTime.now());
        trade.setTradeType("支取");
        trade.setTradeMoney(BigDecimal.valueOf(amount));
        trade.setRemark(remark);
        trade.setCreateTime(LocalDateTime.now());
        trade.setUpdateTime(LocalDateTime.now());
        tradeMapper.insert(trade);
    }
} 